﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace StateManager
{
    class MultiPlayerLevel : Level
    {
        Player[] player;
        // in this level class, we need to keep an array of players because there will be more than one player
        // and the total amount of players never deviates
        // i could have thrown them in a list
        LZone[] chairs;
        // an array of landing zones which will 
        Texture2D playerHud;
        // players hud


        public MultiPlayerLevel(IServiceProvider serviceProvider, Stream fileStream, SpriteBatch spriteBatch,
            int x, int y, int levelNumber, int numOfPlayers, ref bool[] isAlive)
            : base(serviceProvider, fileStream, spriteBatch, x, y, levelNumber)
        {
            int places = 0;
            player = new Player[numOfPlayers];

            foreach (bool alive in isAlive) // run through each bool in array list
                if (alive) // if the frog is alive
                    places++; // total amount of places increases
           
                chairs = new LZone[places - 1]; // the amount of landing zones equals to the amount alive
            
            for (int i = 0; i < numOfPlayers; i++)
            {
                player[i] = new Player(this, i, isAlive[i]); // create new player, feed it info (such as if its alive)

                if (i < chairs.Length) // runs through same loop, creates new landing zones
                    chairs[i] = new LZone((1280 / places) * (i + 1), this);
            }

            playerHud = Content.Load<Texture2D>("images/hud"); // new player hud
        }

        

        public override void updateLevel(KeyboardState kps,GameTime gameTime,GamePadState[] gpses, 
            ref bool[] isAlive, ref bool[]whoLanded)
        {

            checkLocation[] chk = new checkLocation[player.Length];
            checkLocation[] test = new checkLocation[player.Length];

            bool[] isLog = new bool[player.Length];
            bool[] isCrocDead = new bool[player.Length];
            float[] vel = new float[player.Length];
            int[] dir = new int[player.Length];

            // arrays of vars used, one element for each player

            // each array equals the size of the frog


            for (int i = 0; i < player.Length; i++)
            {
                // initialise each of the arrays
                // i don't think i have to do this
                dir[i] = 0;
                isLog[i] = false;
                isCrocDead[i] = false;
                vel[i] = 0;
                player[i].Update(kps, gpses[i], gameTime); // performs update method for all players
            }


            for (int x = 0; x < MAXLANES; x++)
            {
                for (int y = 0; y < MAXCARS; y++)
                {

                    logs[x, y].Update(gameTime, viewPort);
                    cars[x, y].Update(gameTime, viewPort);
                    // update all cars and logs(crocs, turtles)

                    for (int i = 0; i < player.Length; i++)
                    {
                        if (!player[i].HasWon && player[i].IsAlive) // if the player hasn't won but is still alive
                        {

                            handleCollisions(cars[x, y], player[i]); // check for car collisions
                            
                            isAlive[i] = !player[i].isDead;  // the array of players is alive is assigned the opposite of what the player is
                            test[i] = logs[x, y].HandleCollisions(this, player[i]);
                            // logs use a seperate collision method since it's a bit more complicated than the cars
                            if (test[i] != checkLocation.onGround)
                            {
                                // this code runs on a priority basis, one enum has a higher priority than another
                                if (!isLog[i] && test[i] != checkLocation.onLog && !isCrocDead[i] && test[i] != checkLocation.crocbite)
                                    chk[i] = test[i];
                                else if (test[i] == checkLocation.onLog || test[i] == checkLocation.crocbite || test[i] == checkLocation.turtledrown)
                                {



                                    //if (test[i] == checkLocation.onLog)
                                    //    isLog[i] = true;

                                    //if (test[i] == checkLocation.crocbite)
                                    //    isCrocDead[i] = true;

                                    switch (test[i]) // better off using a switch case than using an endless amount of ifs
                                    {
                                        case checkLocation.onLog:
                                            isLog[i] = true;
                                            break;
                                        case checkLocation.crocbite:
                                            isCrocDead[i] = true;
                                            break;
                                    }

                                    if (!isLog[i] || !isCrocDead[i])
                                        chk[i] = test[i];

                                    if (test[i] == checkLocation.onLog)
                                    {
                                        vel[i] = logs[x, y].Vel.X;
                                        dir[i] = (int)logs[x, y].dir;
                                    }
                                    // this is painful but that's what i came up in a short space of time
                                }

                            }
                        }
                    }

                }

            }
            for (int i = 0; i < player.Length;i++)
            {
                for (int j = 0; j < chairs.Length; j++) // this for loop thing checks to see if there was a collision between the landing zones and the player(s)
                {
                    if (chairs[j].colRec.Intersects(player[i].plyrRect) && !player[i].HasWon)
                    {

                        player[i].playerWin();
                        chairs[j].landed();
                        chairs[j].ColorLanded = player[i].FrogColor;
                        whoLanded[i] = true;
                        playSound(4);
                        allZonesFilled++;
                        // set player to win, set chair to landed, set frog on top to frog colour, set bool on ref bool wholanded
                        // play a sound and then set num on allzonesfilled by 1
                    }
                }
                switch (chk[i]) // check the enum each of the logs gives
                {
                    case checkLocation.drowning:
                        player[i].killPlayer('d');

                        if (!player[i].HasWon)
                            playSound(3);
                        break;
                    case checkLocation.turtledrown:
                        player[i].killPlayer('d');

                        if (!player[i].HasWon)
                            playSound(3);
                        break;
                    case checkLocation.crocbite:
                        player[i].killPlayer('c');

                        playSound(2);
                        break;
                    case checkLocation.onLog:
                        player[i].movePlayer(vel[i], (Direction)dir[i]);
                        break;
                    case checkLocation.onGround:
                        break;
                    default:
                        break;
                }
            }


        }

        public override void Draw(GameTime gameTime, SpriteBatch sb)
        {

            DrawTiles(sb); // draw tiles
            float landZoneOffset = viewPort.Width / 4;  // get space for each of the landing zones

            for (int x = 0; x < MAXLANES; x++)
            {
                for (int y = 0; y < MAXCARS; y++)
                {
                    logs[x, y].Draw(sb,gameTime); // draw all logs
                    
                }
            }

            for (int i = 0; i < player.Length; i++)
            {
                if (i < chairs.Length)
                    chairs[i].Draw(sb, gameTime); // draw landing zones

                player[i].Draw(sb, gameTime); // draw player
                if (!player[i].isDead)
                {
                    // draw hud & info if player is not dead
                    sb.Draw(playerHud, new Vector2((landZoneOffset * i), 0), player[i].FrogColor);
                    sb.DrawString(menuFont, "lives:" + player[i].Lives.ToString(), new Vector2((landZoneOffset * i + 180), 0), Color.White);
                }
            }

            for (int x = 0; x < MAXLANES; x++)
            {
                for (int y = 0; y < MAXCARS; y++)
                {
                    cars[x, y].Draw(sb, gameTime); // draw cars
                }
            }
            // this is so that the player doesn't overlap the car and the player overlaps the logs
        }
    }
}
